import { Prefab,Node, instantiate, Vec2, Vec3 } from "cc";
import { SkillType } from "../utils/Config";
import { JoyStickManager } from "../utils/JoyStickManager";


export class SkillCtrl
{
    protected m_skillId : SkillType = 0;
    protected m_skillPfb : Prefab = null;
    protected m_skillNode : Node[] = [];
    protected m_heroNode : Node = null;
    protected m_cd : number = 0; //s
    protected m_dt : number = 0; // 
    protected m_releaseType : number = 0; // 0 : error, 1 : once , 2 : duration
    protected m_duration : number = 0; //s
    protected m_harm : number = 0;
    protected m_range : number = 0;
    protected m_speed : number = 0;
    protected m_pos : Vec3 = null;
    protected m_num : number = 0;

    constructor(skillId : SkillType,skillPfb : Prefab,heroNode : Node)
    {
        this.m_skillId = skillId;
        this.m_skillPfb = skillPfb;
        this.m_heroNode = heroNode;
    }

    private checkIsActivation()
    {
        let rst = false;
        if(this.m_releaseType == 0) // error ,undefine
        {
            this.m_dt = 0;
        }
        else if(this.m_releaseType == 1)    // once
        {
            if(this.m_cd == 0 || this.m_dt >= this.m_cd)
            {
                this.m_dt = 0;
                rst = true;
            }
            else
            {
                rst = false;
            }
        }
        else if(this.m_releaseType == 2)  //duration
        {
            if(this.m_duration == 0)
            {
                rst = false;
            }
            else if(this.m_dt > this.m_duration && this.m_dt < (this.m_cd + this.m_duration))
            {
                rst = false;
            }
            else
            {
                rst = true;
            }
            this.m_dt %= (this.m_cd + this.m_duration);
        }
        for(let i=0;i<this.m_skillNode.length;++i)
        {
            if(this.m_skillNode[i])
            {
                this.m_skillNode[i].active = rst;
            }
        }
        return rst;
    }

    public initSkill(){}

    public incrSkill(num : number = 1){}

    public update(dt : number)
    {
        this.m_dt += dt;
        if(this.checkIsActivation())
        {
            this.onRelease(dt);
        }
    }

    public onRelease(dt : number) {}
}

export class UnDefineSkillCtrl extends SkillCtrl
{
    constructor(skillId : SkillType,skillPfb : Prefab,heroNode : Node)
    {
        super(skillId,skillPfb,heroNode);
        this.m_releaseType = 1;
        this.m_cd = 5;
    }

    public onRelease(dt: number): void {
        
    }
    
}

export class TrackSkillCtrl extends SkillCtrl
{
    private parentNode : Node = null;

    constructor(skillId : SkillType,skillPfb : Prefab,heroNode : Node,pNode : Node)
    {
        super(skillId,skillPfb,heroNode);
        this.m_releaseType = 1;
        this.m_cd = 5;
        this.m_num = 3;
        this.parentNode = pNode;
    }

    getRandomNodes()
    {
        let allai : Node[] = this.parentNode.getComponent("AiPoolCtrl").getAllAi();
        if(allai.length <= 0) return [];
        const result: Node[] = [];  
        while (result.length < this.m_num) {  
            // 随机选择一个索引  
            const randomIndex = Math.floor(Math.random() * allai.length);  
            // 将对应索引的Node添加到结果数组中  
            result.push(allai[randomIndex]);  
        }  
        return result;  
    }

    public onRelease(dt: number): void {
        const resultNodes : Node[] = this.getRandomNodes();
        if(resultNodes.length < this.m_num)
        {
            console.log("error,not found n ai,",this.m_num);
            return;
        }
        for(let i=0;i<this.m_num;++i)
        {
            let skill : Node = instantiate(this.m_skillPfb);
            skill.setPosition(this.m_heroNode.getPosition());
            this.parentNode.addChild(skill);
            skill.getComponent("TrackSkillCtrl").setTarget(resultNodes[i]);
        }
    }
}

export class BulletSkillCtrl extends SkillCtrl
{
    private parentNode : Node = null;

    constructor(skillId : SkillType,skillPfb : Prefab,heroNode : Node,pNode : Node)
    {
        super(skillId,skillPfb,heroNode);
        this.m_releaseType = 1;
        this.m_cd = 0.25;
        this.m_speed = 50;
        this.parentNode = pNode;
    }

    public onRelease(dt: number): void {
        if(this.m_heroNode == null || this.m_skillPfb == null || this.parentNode == null) return ;
        let dir : Vec3 = JoyStickManager.GetInstance().joyStick.getDir();
        let normalizedDirection = new Vec2(0,0);
        Vec2.normalize(normalizedDirection,dir);
        if(normalizedDirection.x == 0 && normalizedDirection.y == 0) 
        {
            normalizedDirection.x = normalizedDirection.y = 1;
        }
        let initPos = this.m_heroNode.getPosition();
        const moveDistance = this.m_speed * 0.015;
        const scaledDirection = new Vec2(moveDistance*normalizedDirection.x,moveDistance*normalizedDirection.y);
        initPos.x += scaledDirection.x;
        initPos.y += scaledDirection.y;
        
        // create 
        let bulletNode : Node = instantiate(this.m_skillPfb);
        bulletNode.setPosition(new Vec3(initPos.x,initPos.y + 20,0));
        this.parentNode.addChild(bulletNode);
        bulletNode.getComponent("BulletCtrl").setDirection(normalizedDirection);
    }
}

export class SurroundSkillCtrl extends SkillCtrl
{
    private m_angle: number = 0;  
    private m_skillAngle : number[] = []
    constructor(skillId : SkillType,skillPfb : Prefab,heroNode : Node)
    {
        super(skillId,skillPfb,heroNode);
        this.m_releaseType = 2;
        this.m_range = 350; // 半径
        this.m_speed = 200;
        this.m_pos = new Vec3(0,0,0); // 中心点
        this.m_cd = 3;
        this.m_duration = 6;
    }

    onRelease(dt : number): void {
        if(this.m_heroNode == null || this.m_skillPfb == null) return ;
        
        for(let i=0;i<this.m_skillNode.length;++i)
        {
            this.m_skillAngle[i] += this.m_speed * dt;
            if(this.m_skillAngle[i] >= 360) 
            {
                this.m_skillAngle[i] -= 360;
            }

            let curPos = this.m_pos;
            const x = curPos.x + this.m_range * Math.cos(this.m_skillAngle[i] * Math.PI / 180);
            const y = curPos.y + this.m_range * Math.sin(this.m_skillAngle[i] * Math.PI / 180); 
            this.m_skillNode[i].setPosition(new Vec3(x,y,0));
            //console.log("skill pos: ",x,y);
        }
        //console.log("offset : ",offsetX,offsetY);
    }

    private adjustSkillPos()
    {
        this.m_skillAngle = []
        for(let i=0;i<this.m_skillNode.length;++i)
        {
            const angle = (i*360) / this.m_skillNode.length;
            const x = this.m_pos.x + this.m_range * Math.cos(angle * Math.PI / 180); //
            const y = this.m_pos.y + this.m_range * Math.sin(angle * Math.PI / 180); // 
            this.m_skillNode[i].setPosition(new Vec3(x,y,0));
            console.log("skill pos: ",x,y);
            this.m_skillAngle.push(angle);
        }
    }

    public initSkill(): void {
        this.incrSkill(4);
    }

    public incrSkill(num?: number): void {
        if(this.m_skillPfb == null || this.m_heroNode == null) return;
        for(let i=0;i<num;++i)
        {
            let skillNode : Node = instantiate(this.m_skillPfb);
            this.m_heroNode.addChild(skillNode);
            this.m_skillNode.push(skillNode);
        }
        this.adjustSkillPos();
    }
}